package com.barnett.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;

public abstract class BaseView extends View implements OnGestureListener {
	/**
	 * 将原始的触摸事件转换成手势
	 * ，如果你从onDown()方法中返回false，比如GestrueDetector.SimpleOnGestureListener这么做了，
	 * 那么系统会认为你选择忽略这个手势操作的其余部分
	 * ，这样的话GestrueDetector.OnGestureListener的其他方法将不会再被调用
	 * 。你需要在onDown()方法中返回false的时候是你真的想要忽略一个完整的手势操作。
	 */
	protected GestureDetector gestureDetector;

	public BaseView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		init();
		init(context, attrs);
	}

	public BaseView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init();
		init(context, attrs);
	}

	public BaseView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		init();
		init(context, null);
	}

	private void init() {
		gestureDetector = new GestureDetector(getContext(), this);
	}

	/** 手势监听 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (gestureDetector == null) {
			return super.onTouchEvent(event);
		}
		return gestureDetector.onTouchEvent(event);
	}

	/** 是否为高版本 */
	protected boolean isHVersion() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
	}

	/** 启动硬件加速 */
	@SuppressLint("NewApi")
	protected void hardware() {
		if (isHVersion()) {
			// 包含新API的代码块
			if (!isInEditMode()) {
				setLayerType(View.LAYER_TYPE_HARDWARE, null);// 硬件加速
			}
		} else {
			// 包含旧的API的代码块
			setLayerType(View.LAYER_TYPE_NONE, null);// view按一般方式绘制，不使用离屏缓冲．这是默认的行为．
		}
	}

	/** resolveSizeAndState所需的参数 低版本不自带 */
	private final int MEASURED_STATE_TOO_SMALL = 0x01000000;
	private final int MEASURED_STATE_MASK = 0xff000000;

	/** 帮助计算空间所需的大小 */
	protected int resolveSizeAndState2(int size, int measureSpec,
			int childMeasuredState) {
		int result = size;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);
		switch (specMode) {
		case MeasureSpec.UNSPECIFIED:
			result = size;
			break;
		case MeasureSpec.AT_MOST:
			if (specSize < size) {
				result = specSize | MEASURED_STATE_TOO_SMALL;
			} else {
				result = size;
			}
			break;
		case MeasureSpec.EXACTLY:
			result = specSize;
			break;
		}
		return result | (childMeasuredState & MEASURED_STATE_MASK);
	}
	/** 初始化 */
	protected abstract void init(Context context, AttributeSet attrs);

	/** 获得当前空间大小改变 */
	@Override
	protected abstract void onSizeChanged(int w, int h, int oldw, int oldh);
	/** 尝试获得足够大的区域 */
	@Override
	protected abstract void onMeasure(int widthMeasureSpec,
			int heightMeasureSpec);

	// ////////////////// 以下为手势监听部分 ///////////////////////////
	/** 一次点击up事件；在touch down后又没有滑动 */
	@Override
	public abstract boolean onSingleTapUp(MotionEvent arg0);

	/** down事件发生而move或则up还没发生前触发该事件 */
	@Override
	public abstract void onShowPress(MotionEvent arg0);

	/** 在屏幕上拖动事件。无论是用手拖动view，或者是以抛的动作滚动，都会多次触发,这个方法在ACTION_MOVE动作发生时就会触发 */
	@Override
	public abstract boolean onScroll(MotionEvent arg0, MotionEvent arg1,
			float arg2, float arg3);

	/** 长按事件；Touch了不移动一直Touch down时触发 */
	@Override
	public abstract void onLongPress(MotionEvent arg0);

	/**
	 * 需要开始滑动，可以通过一个开始的速率以及一个最小和最大的x和y的滑动值调用fling()方法。想要得到速率的值，
	 * 你可以通过GestureDetector来计算这个值。一般情况下将x和y值除以4-8的值
	 */
	@Override
	public abstract boolean onFling(MotionEvent e1, MotionEvent e2,
			float velocityX, float velocityY);

	/** down事件 最好设置为return true*/
	@Override
	public abstract boolean onDown(MotionEvent arg0);
}
